﻿
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity.Validation;
using OnlineMealOrdering.Domain;
using OnlineMealOrdering.Common;
using OnlineMealOrdering.Domain.Base;


namespace OnlineMealOrdering.Persistence
{
    public class OnlineStoreDbContext : DbContext
    {
        public int AuthorId { get; set; }
        public DbSet<UserEntity> Users { get; set; }
        public DbSet<RoleEntity> Roles { get; set; }
        public DbSet<AddressEntity> Address { get; set; }
        public DbSet<CouponEntity> Coupons { get; set; }
        public DbSet<FoodCatalogEntity> FoodCatalogs { get; set; }
        public DbSet<FoodEntity> Foods { get; set; }
        public DbSet<ImageEntity> Images { get; set; }
        public DbSet<NoticeEntity> Notices { get; set; }
        public DbSet<OrderEntity> Orders { get; set; }
        public DbSet<ShopItemEntity> ShopItems { get; set; }
        public DbSet<ShopCarEntity> ShopCars { get; set; }
        public DbSet<StoreCommentEntity> StoreComments { get; set; }
        public DbSet<StoreOnlineEntity> StoreOnlines { get; set; }

        public DbSet<TagEntity> Tags { get; set; }

        public OnlineStoreDbContext()
            : base()
        {
        }

        public OnlineStoreDbContext(int authorId)
            : base()
        {
            AuthorId = authorId;
        }


        public OnlineStoreDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
        }


        public OnlineStoreDbContext(DbConnection existingConnection, bool contextOwnsConnection)
            : base(existingConnection, contextOwnsConnection)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

            //modelBuilder.Conventions.Remove<IncludeMetadataConvention>();



            var roleConfig = modelBuilder.Entity<RoleEntity>();
            roleConfig.HasMany<UserEntity>(a => a.Users).WithMany(a => a.Roles).Map(a => a.ToTable("Role_User"));

            modelBuilder.Entity<FoodEntity>().HasMany<ImageEntity>(a => a.Images).WithMany().Map(a => a.ToTable("Food_Image"));

            modelBuilder.Entity<StoreOnlineEntity>().HasMany<TagEntity>(a => a.Tags).WithMany().Map(a => a.ToTable("StoreOnline_Tags"));

            //modelBuilder.Entity<StoreOnlineEntity>().HasMany<FoodEntity>(a => a.Foods).WithMany().Map(a => a.ToTable("StoreOnline_Foods"));

            modelBuilder.Entity<OrderEntity>().HasMany<ShopItemEntity>(a => a.Details).WithMany().Map(a => a.ToTable("Order_Details"));

            modelBuilder.Entity<ShopCarEntity>().HasMany<ShopItemEntity>(a => a.Details).WithMany().Map(a => a.ToTable("ShopCar_Details"));

            modelBuilder.Entity<StoreOnlineEntity>().HasMany<MarkEntity>(a => a.Marks).WithMany().Map(a => a.ToTable("StoreOnline_Marks"));

            modelBuilder.Entity<StoreOnlineEntity>().HasMany<FoodCatalogEntity>(a => a.Catalogs).WithMany().Map(a => a.ToTable("StoreOnline_Catalogs"));

            //店铺和配送区域多边形坐标
            modelBuilder.Entity<StoreOnlineEntity>().HasMany<AreaCoordinateEntity>(a => a.AreaCoordinate).WithMany().Map(a => a.ToTable("StoreOnline_AreaCoordinate"));

        }


        public override int SaveChanges()
        {
            var author = Users.Find(AuthorId);
            FillAuditableInfo(author);
            int saveResult = 0;
            try
            {
                saveResult = base.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                throw BusinessException.Create(GetEntityValidationErrorMessage(ex));
            }
            return saveResult;
        }

        string GetEntityValidationErrorMessage(DbEntityValidationException exception)
        {
            string message = string.Empty;
            var entityValidationErrors = exception.EntityValidationErrors;
            foreach (DbEntityValidationResult validationResult in entityValidationErrors)
            {
                var validationErrors = validationResult.ValidationErrors;
                foreach (var error in validationErrors)
                {
                    message += error.ErrorMessage;
                }
            }

            return message;
        }


        void FillAuditableInfo(UserEntity author)
        {
            var nowAuditDate = DateTime.Now;
            var changeSet = ChangeTracker.Entries<IAuditable>();

            if (changeSet != null)
            {
                foreach (DbEntityEntry<IAuditable> dbEntityEntry in changeSet)
                {
                    switch (dbEntityEntry.State)
                    {
                        case EntityState.Added:
                            dbEntityEntry.Entity.CreatedDate = nowAuditDate;
                            dbEntityEntry.Entity.CreatedBy = author;
                            dbEntityEntry.Entity.UpdatedDate = nowAuditDate;
                            dbEntityEntry.Entity.UpdatedBy = author;
                            break;
                        case EntityState.Modified:
                            dbEntityEntry.Entity.UpdatedDate = nowAuditDate;
                            dbEntityEntry.Entity.UpdatedBy = author;
                            break;
                    }
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }
    }
}
